<?php
namespace db;

/**
 * 制作:  叶风
 * Qq:    355007778
 * Email: ye.fn@163.com
 */


class mysqli
{
	public $pre, $charset, $dataname;
    
    static protected $_C = array(); 
    protected $link, $result, $_tableA = array(), $_whereA = array(),$_byGroup='';

	//构造函数，执行连接数据库
	function __construct($con)
	{
		$this->pre = $con['pre'];
		$this->charset = $con['charset'];
		$this->dataname = $con['data'];
        
		$this->link = new \mysqli($con['host'], $con['user'], $con['pass'], $con['data']);
        if ($this->link->connect_error)
			\YF_f::error($this->link->connect_error, 0);
		if ($this->charset)
			$this->link->set_charset($this->charset);
		if ($con['time_zone'] )
			$this->query('set time_zone = "'. $con['time_zone'] .'"');		
	}
    function close()
    {
        if ($this->link){
            $this->link->close();
            unset($this->link);
         }
    }
    
    /**
     * 克隆链接
     * @param type $n
     * @return \db\mysqli
     */
    function C($n)
    {
        if (isset(self::$_C[$n]))
            return self::$_C[$n];
        
        $c  = clone $this;
        $c->clq();
        self::$_C[$n] = $c;
        return $c;   
    }
    /**
	 * 执行SQL
	 * $debug = 1 显示出错|2 出错时中断
	 *
	 */
	function query($sql)
	{
        $this->result = $this->link->query($sql);
        if (\YF_f::$config['debug']>2)
        	\YF_f::$arr['debug_info'][] = $sql;
        
        if (!$this->result)
        	\YF_f::error($this->link->error.': '.$sql, 2);
		return $this->result;
	}
	function select_db($name)
	{
		$this->link->select_db($name) or \YF_f::error($this->link->error);
	}
	// 开始事务
	function sqlS($end=FALSE)
	{
		$this->link->autocommit($end);
	}
	// 提交事务
	function sqlE()
	{
		$this->link->commit();
		$this->link->autocommit(TRUE);
	}
    // 回滚事务
	function sqlB()
	{
		$this->link->rollback();
		$this->link->autocommit(TRUE);
	}	
	//获取插入ID
	function insert_id()
	{
		return $this->link->insert_id;
	}
	//获取操作的行数
	function num_affected()
	{	
		return $this->link->affected_rows;
	}
	//获取查询的行数
	function num_rows()
	{
		if( $this->result )
			return $this->result->num_rows();
	}
/**
 * 过滤
 */
	function escape($str)
	{
		return $this->link->real_escape_string($str);
	}
    function escape_a($a, $glue='","')
    {
        return implode($glue, array_map(array(self, 'escape'), $a));
    }
    function realField($s)
    {
        return preg_replace("|[^a-zA-Z0-9_.-]+|", '', $s);
    }
    /**
     * 
     * @param type $tables 表名, 也可以为数组 array('t'=>'', 't2'=>array('join'=>'','on'=''))
     * @param type $field  字段名，表名=false时，作为 SQL 语句
     * @param type $where
     * @param type $order
     * @param type $limit
     * @return string
     */
	function ssql($tables, $field,  $where='', $order='', $limit='')
	{
        if ($tables===FALSE)
            $sql = $field;
        else {
            $table = $this->tables2sql($tables);
            $sql = 'SELECT '. $field  .' FROM '. $table;
         }            
		
		$w = $this->_whereA;
		if($where)
            $w[] =  $where;
        if($w)
            $sql .= ' WHERE '.implode (' AND ', $w);

		if($this->_byGroup )
          {
            $sql .= ' GROUP BY '. $this->_byGroup;
            $this->_byGroup = '';
          }
		
		$order && $sql .= ' ORDER BY '. $order;
		$limit && $sql .= ' LIMIT '. $limit;
		return $sql;
	}
    function table($n, $jo='', $on='', $as='')
    {
        $this->_tableA[$n] = array('join'=>$jo, 'on'=>$on,'as'=>$as);
        return $this;
    }
    protected function tables2sql($tables)
    {
        if (!is_array($tables))
            $tables =array("$tables"=>'');
        if ($this->_tableA)
            $tables = array_merge($this->_tableA, $tables);
        $table = '';
        foreach($tables as $k=>$v)
         {  
            $tb = isset($v['as']) ? $v['as'] : $k;
            $on = isset($v['on']) ? "ON($v[on])" : '';
            $jo = isset($v['join']) ? $v['join'] : '';
            $table .= " $jo `{$this->pre}$tb`  `$k`  $on";
         }
        return $table;
    }
	function where($f, $p)
	{
        if (!is_array($parse)) 
         {
            $p = func_get_args();
            array_shift($p);
         }        
        $p = array_map(array($this, 'escape'),$p);
		$this->_whereA[] = vsprintf($f,$p);
		return $this;
	}
    function group($s)
    {
        $this->_byGroup = $s;
        return $this;
    }
    // 清空 sql
	function clq()
	{
		$this->_whereA = $this->_tableA = array();
        $this->_byGroup = '';
        $this->result = null;
		return $this;
	}
	/**
     * 查询所有行
     * 
     * @param array $tables
     * @param string $field
     * @param string $where
     * @param string $order
     * @param string $limit
     * @return array
     */
	function get($tables, $field='*',  $where='', $order='', $limit='', $b=MYSQLI_ASSOC)
	{
        $sql = $this->ssql($tables, $field,  $where, $order, $limit);
		if ($this->query($sql) )
		 {
		 	$res = $this->result->fetch_all($b); 
			$this->result->free();
			return $res;
		 }
		return  array();
	}
	function getCol($tables, $field, $where='', $order='', $limit='')
	{
        $res = $this->get($tables, $field,  $where, $order, $limit, MYSQLI_NUM);
		$colA = array();
		foreach($res as $row)
            $colA[] = $row[0];
		return $colA;
	}
    
    /**
     *  分页查询  
     * @param array $arr (
     *    $limit 页条数
     *    $page_li  按扭数
     *    $getCol 
     *  )
     * @param array $tables
     * @param string $field
     * @param string $where
     * @param string $order
     * @return array
     */
	function get_page($arr, $tables, $field='*',  $where='', $order='')
	{
        $G = $_GET;
        // 页数
		$G['p'] && $arr['p'] = intval($G['p']);
		$arr['p'] < 1 &&  $arr['p']=1;
		// 条数
        $limit = '';
        if (!$arr['limit'])
            $arr['limit'] =  \YF_f::$config['paging_limit'];
        
        if ($G['limit']=='all')
            set_time_limit(0);
        else{           
            if ($G['limit'])
             {
               $mylimit = intval($G['limit']);
               if ($mylimit>0)
                {
                   if ($mylimit>9000)
                       set_time_limit(0);
                   $arr['limit'] = $mylimit;
                }
             }
            if (isset($G['limitS']))
                $limit = intval($G['limitS']) .',' .$arr['limit'];
            else
                $limit = ($arr['p'] -1) * $arr['limit'] .',' .$arr['limit'];
        }
        
		// get
        $field = $tables ? 'SQL_CALC_FOUND_ROWS  '. $field 
					 	 : substr_replace($field, ' SQL_CALC_FOUND_ROWS ', 7,0);
		if (isset($arr['re_col']))
            $res = $this->getCol($tables, $field, $where, $order, $limit);
        else
            $res = $this->get($tables, $field, $where, $order, $limit);
        
		// 总数
		$arr['num'] = $this->getOneField(false, 'SELECT FOUND_ROWS()');
		$this->pages($arr);
        
		return $res;
	}
    /**
     * 分页数
     * 
     * @var type array(
     *    $p  当前页
     *    $pages 总页
     *    $num   总条数
     *    $limit 页条数
     *    $page_li  按扭数
     *  )
     */
    var $paging = array();
    private function pages($arr)
	{
		extract($arr);
		$paging = array();
		$paging['p'] = $p; 	//本页
		$paging['num'] = $num;  //总条数
		$paging['limit'] = $limit; //每页条数
		$paging['pages'] = $pages = ceil($num / $limit); //页数
		$paging['page_li'] = array();
        
		if ($pages >1)
         {
            $page_li<1 && $page_li = 9;  // 按钮数
            $li_c = $p>3 ? $p-3 : 0;
            $li_c = $li_c -  $li_c % $page_li + 2; // S
            $page_li += $li_c + 1 ;
            $page_li > $pages  && $page_li = $pages; // E
            $paging['page_li'][1]  = 1; //第一
            for (; $li_c<=$page_li; $li_c++)
                $paging['page_li'][$li_c] = $li_c;  
            $paging['page_li'][$pages] = $pages;//最后
         }
		$this->paging = $paging;
	}

	function getOneField($tables, $field, $where='', $order='', $limit=0)
	{
		$sql = $this->ssql($tables, $field,  $where, $order, $limit.',1');
		if( $this->query($sql) )
		 {
			$row = $this->result->fetch_row();
			$this->result->free();
			return $row[0];
		 }
	}
	function getOne($tables, $field='*', $where='', $order='',$limit='')
	{
		$sql = $this->ssql($tables, $field,  $where, $order, $limit);
		if( $this->query($sql) )
		 {
		 	$res = $this->result->fetch_array(MYSQLI_ASSOC);
			$this->result->free();
			return $res;
		 }
		return  array();
	}
    // 生成唯一ID
    function creID($t, $f='id', $pre='', $b='10')
    {
        do{
            $val = $pre . randomkeys(mt_rand(1,50), $b); 
        }while ($this->getOne($t, "*", "$f='$val'"));
        return $val;
    }
    /**
     * 保存数据
     * @param type $table
     * @param type $data  数组的键名为表名，键值也为一个数组，键名为字段，键值为数据
     * @param type $where
     * @param type $b  为1，不格式
     * @return type
     */
	function save($table, $data, $where='', $b=FALSE)
	{
		if( !is_array($data))
			return;
		$sql = '';
		if($b)
			foreach($data as $k=>$v)
              {
                $k = $this->realField($k);
				$sql .= ", `$k`=$v";
              }
		else
			foreach($data as $k=>$v)
			 {
			 	$k = $this->realField($k);
				switch (gettype($v))
				 {
					case 'integer':
					case 'double':
						 $sql .= ", `$k`=$v";
						break;
					case 'NULL': 
						$sql .= ", `$k`=NULL";
						break;
					default:
						if($v)
							$v = $this->escape($v);
						$sql .= ", `$k`='$v'";
				 }
			 }
	
		$sql = substr($sql, 1);
		
		$at = $this->pre.$table;
        if ($where==='REPLACE' )
			$sql = "REPLACE INTO `$at` SET $sql";
        elseif ($where)
            $sql = "UPDATE `$at` as `$table` SET $sql WHERE $where";
        else
            $sql = "INSERT INTO `$at` SET $sql";	
        
        return $this->query($sql);
	}
    /**
     * 字段值磊加
     * @param type $table
     * @param type $f  字段
     * @param type $ids  条件
     * @param type $v  需要安全的，不设置为原值加1
     * @return boolean
     */
	function upField($table, $f, $ids, $v=1)
	{
		return $this->query("UPDATE `{$this->pre}$table` SET `$f`=$f + $v WHERE id IN($ids)");
	}
    /**
     * 删除
     * @param type $tables
     * @param type $where
     * @param string $delT
     * @return boolean
     */
    function del($tables, $where, $delT='')
    {
        if (!is_array($tables))
                $tables =array("$tables"=>'');
        if (!$delT)
            $delT = implode (',', array_keys($tables));
        
        $table = $this->tables2sql($tables);
        $sql = 'DELETE '. $delT  .' FROM '. $table;
        
        $w = $this->_whereA;
		if ($where)
            $w[] =  $where;
        if ($w)
            $sql .= ' WHERE '.implode (' AND ', $w);
        
    	return $this->query($sql);
    }
   
}
?>